home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / BaseClasses / videoctl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  21.0 KB  |  654 lines

  1. //------------------------------------------------------------------------------
  2. // File: VideoCtl.cpp
  3. //
  4. // Desc: DirectShow base classes.
  5. //
  6. // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. #include <streams.h>
  11. #include "ddmm.h"
  12.  
  13. // Load a string from the resource file string table. The buffer must be at
  14. // least STR_MAX_LENGTH bytes. The easiest way to use this is to declare a
  15. // buffer in the property page class and use it for all string loading. It
  16. // cannot be static as multiple property pages may be active simultaneously
  17.  
  18. TCHAR *WINAPI StringFromResource(TCHAR *pBuffer, int iResourceID) {
  19.     if(LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
  20.         return TEXT("");
  21.     }
  22.     return pBuffer;
  23. }
  24.  
  25. #ifdef UNICODE
  26. char *WINAPI StringFromResource(char *pBuffer, int iResourceID) {
  27.     if(LoadStringA(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
  28.         return "";
  29.     }
  30.     return pBuffer;
  31. }
  32. #endif
  33.  
  34.  
  35.  
  36. // Property pages typically are called through their OLE interfaces. These
  37. // use UNICODE strings regardless of how the binary is built. So when we
  38. // load strings from the resource file we sometimes want to convert them
  39. // to UNICODE. This method is passed the target UNICODE buffer and does a
  40. // convert after loading the string (if built UNICODE this is not needed)
  41. // On WinNT we can explicitly call LoadStringW which saves two conversions
  42.  
  43. #ifndef UNICODE
  44.  
  45. WCHAR * WINAPI WideStringFromResource(WCHAR *pBuffer, int iResourceID) {
  46.     *pBuffer = 0;
  47.  
  48.     if(g_amPlatform == VER_PLATFORM_WIN32_NT) {
  49.         LoadStringW(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH);
  50.     }
  51.     else {
  52.  
  53.         CHAR szBuffer[STR_MAX_LENGTH];
  54.         DWORD dwStringLength = LoadString(g_hInst,iResourceID,szBuffer,STR_MAX_LENGTH);
  55.         // if we loaded a string convert it to wide characters, ensuring
  56.         // that we also null terminate the result.
  57.         if(dwStringLength++) {
  58.             MultiByteToWideChar(CP_ACP,0,szBuffer,dwStringLength,pBuffer,STR_MAX_LENGTH);
  59.         }
  60.     }
  61.     return pBuffer;
  62. }
  63.  
  64. #endif
  65.  
  66.  
  67. // Helper function to calculate the size of the dialog
  68.  
  69. BOOL WINAPI GetDialogSize(int iResourceID,
  70.                           DLGPROC pDlgProc,
  71.                           LPARAM lParam,
  72.                           SIZE *pResult) {
  73.     RECT rc;
  74.     HWND hwnd;
  75.  
  76.     // Create a temporary property page
  77.  
  78.     hwnd = CreateDialogParam(g_hInst,
  79.         MAKEINTRESOURCE(iResourceID),
  80.         GetDesktopWindow(),
  81.         pDlgProc,
  82.         lParam);
  83.     if(hwnd == NULL) {
  84.         return FALSE;
  85.     }
  86.  
  87.     GetWindowRect(hwnd, &rc);
  88.     pResult->cx = rc.right - rc.left;
  89.     pResult->cy = rc.bottom - rc.top;
  90.  
  91.     DestroyWindow(hwnd);
  92.     return TRUE;
  93. }
  94.  
  95.  
  96. // Class that aggregates on the IDirectDraw interface. Although DirectDraw
  97. // has the ability in its interfaces to be aggregated they're not currently
  98. // implemented. This makes it difficult for various parts of Quartz that want
  99. // to aggregate these interfaces. In particular the video renderer passes out
  100. // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
  101. // graph manager also exposes IDirectDraw as a plug in distributor. For these
  102. // objects we provide these aggregation classes that republish the interfaces
  103.  
  104. STDMETHODIMP CAggDirectDraw::NonDelegatingQueryInterface(REFIID riid, void **ppv) {
  105.     ASSERT(m_pDirectDraw);
  106.  
  107.     // Do we have this interface
  108.  
  109.     if(riid == IID_IDirectDraw) {
  110.         return GetInterface((IDirectDraw *)this,ppv);
  111.     }
  112.     else {
  113.         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  114.     }
  115. }
  116.  
  117.  
  118. STDMETHODIMP CAggDirectDraw::Compact() {
  119.     ASSERT(m_pDirectDraw);
  120.     return m_pDirectDraw->Compact();
  121. }
  122.  
  123.  
  124. STDMETHODIMP CAggDirectDraw::CreateClipper(DWORD dwFlags,LPDIRECTDRAWCLIPPER *lplpDDClipper,IUnknown *pUnkOuter) {
  125.     ASSERT(m_pDirectDraw);
  126.     return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter);
  127. }
  128.  
  129.  
  130. STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags,LPPALETTEENTRY lpColorTable,LPDIRECTDRAWPALETTE *lplpDDPalette,IUnknown *pUnkOuter) {
  131.     ASSERT(m_pDirectDraw);
  132.     return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter);
  133. }
  134.  
  135.  
  136. STDMETHODIMP CAggDirectDraw::CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,LPDIRECTDRAWSURFACE *lplpDDSurface,IUnknown *pUnkOuter) {
  137.     ASSERT(m_pDirectDraw);
  138.     return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter);
  139. }
  140.  
  141.  
  142. STDMETHODIMP CAggDirectDraw::DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface,LPDIRECTDRAWSURFACE *lplpDupDDSurface) {
  143.     ASSERT(m_pDirectDraw);
  144.     return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface);
  145. }
  146.  
  147.  
  148. STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount,LPDDSURFACEDESC lplpDDSurfaceDescList,LPVOID lpContext,LPDDENUMMODESCALLBACK lpEnumCallback) {
  149.     ASSERT(m_pDirectDraw);
  150.     return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback);
  151. }
  152.  
  153.  
  154. STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags,LPDDSURFACEDESC lpDDSD,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumCallback) {
  155.     ASSERT(m_pDirectDraw);
  156.     return m_pDirectDraw->EnumSurfaces(dwFlags,lpDDSD,lpContext,lpEnumCallback);
  157. }
  158.  
  159.  
  160. STDMETHODIMP CAggDirectDraw::FlipToGDISurface() {
  161.     ASSERT(m_pDirectDraw);
  162.     return m_pDirectDraw->FlipToGDISurface();
  163. }
  164.  
  165.  
  166. STDMETHODIMP CAggDirectDraw::GetCaps(LPDDCAPS lpDDDriverCaps,LPDDCAPS lpDDHELCaps) {
  167.     ASSERT(m_pDirectDraw);
  168.     return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps);
  169. }
  170.  
  171.  
  172. STDMETHODIMP CAggDirectDraw::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) {
  173.     ASSERT(m_pDirectDraw);
  174.     return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc);
  175. }
  176.  
  177.  
  178. STDMETHODIMP CAggDirectDraw::GetFourCCCodes(LPDWORD lpNumCodes,LPDWORD lpCodes) {
  179.     ASSERT(m_pDirectDraw);
  180.     return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes);
  181. }
  182.  
  183.  
  184. STDMETHODIMP CAggDirectDraw::GetGDISurface(LPDIRECTDRAWSURFACE *lplpGDIDDSurface) {
  185.     ASSERT(m_pDirectDraw);
  186.     return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface);
  187. }
  188.  
  189.  
  190. STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(LPDWORD lpdwFrequency) {
  191.     ASSERT(m_pDirectDraw);
  192.     return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency);
  193. }
  194.  
  195.  
  196. STDMETHODIMP CAggDirectDraw::GetScanLine(LPDWORD lpdwScanLine) {
  197.     ASSERT(m_pDirectDraw);
  198.     return m_pDirectDraw->GetScanLine(lpdwScanLine);
  199. }
  200.  
  201.  
  202. STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(LPBOOL lpblsInVB) {
  203.     ASSERT(m_pDirectDraw);
  204.     return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB);
  205. }
  206.  
  207.  
  208. STDMETHODIMP CAggDirectDraw::Initialize(GUID *lpGUID) {
  209.     ASSERT(m_pDirectDraw);
  210.     return m_pDirectDraw->Initialize(lpGUID);
  211. }
  212.  
  213.  
  214. STDMETHODIMP CAggDirectDraw::RestoreDisplayMode() {
  215.     ASSERT(m_pDirectDraw);
  216.     return m_pDirectDraw->RestoreDisplayMode();
  217. }
  218.  
  219.  
  220. STDMETHODIMP CAggDirectDraw::SetCooperativeLevel(HWND hWnd,DWORD dwFlags) {
  221.     ASSERT(m_pDirectDraw);
  222.     return m_pDirectDraw->SetCooperativeLevel(hWnd,dwFlags);
  223. }
  224.  
  225.  
  226. STDMETHODIMP CAggDirectDraw::SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp) {
  227.     ASSERT(m_pDirectDraw);
  228.     return m_pDirectDraw->SetDisplayMode(dwWidth,dwHeight,dwBpp);
  229. }
  230.  
  231.  
  232. STDMETHODIMP CAggDirectDraw::WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent) {
  233.     ASSERT(m_pDirectDraw);
  234.     return m_pDirectDraw->WaitForVerticalBlank(dwFlags,hEvent);
  235. }
  236.  
  237.  
  238. // Class that aggregates an IDirectDrawSurface interface. Although DirectDraw
  239. // has the ability in its interfaces to be aggregated they're not currently
  240. // implemented. This makes it difficult for various parts of Quartz that want
  241. // to aggregate these interfaces. In particular the video renderer passes out
  242. // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
  243. // graph manager also exposes IDirectDraw as a plug in distributor. For these
  244. // objects we provide these aggregation classes that republish the interfaces
  245.  
  246. STDMETHODIMP CAggDrawSurface::NonDelegatingQueryInterface(REFIID riid, void **ppv) {
  247.     ASSERT(m_pDirectDrawSurface);
  248.  
  249.     // Do we have this interface
  250.  
  251.     if(riid == IID_IDirectDrawSurface) {
  252.         return GetInterface((IDirectDrawSurface *)this,ppv);
  253.     }
  254.     else {
  255.         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  256.     }
  257. }
  258.  
  259.  
  260. STDMETHODIMP CAggDrawSurface::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) {
  261.     ASSERT(m_pDirectDrawSurface);
  262.     return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface);
  263. }
  264.  
  265.  
  266. STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(LPRECT lpRect) {
  267.     ASSERT(m_pDirectDrawSurface);
  268.     return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect);
  269. }
  270.  
  271.  
  272. STDMETHODIMP CAggDrawSurface::Blt(LPRECT lpDestRect,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwFlags,LPDDBLTFX lpDDBltFx) {
  273.     ASSERT(m_pDirectDrawSurface);
  274.     return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx);
  275. }
  276.  
  277.  
  278. STDMETHODIMP CAggDrawSurface::BltBatch(LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags) {
  279.     ASSERT(m_pDirectDrawSurface);
  280.     return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags);
  281. }
  282.  
  283.  
  284. STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwTrans) {
  285.     ASSERT(m_pDirectDrawSurface);
  286.     return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans);
  287. }
  288.  
  289.  
  290. STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSAttachedSurface) {
  291.     ASSERT(m_pDirectDrawSurface);
  292.     return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface);
  293. }
  294.  
  295.  
  296. STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) {
  297.     ASSERT(m_pDirectDrawSurface);
  298.     return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback);
  299. }
  300.  
  301.  
  302. STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpfnCallback) {
  303.     ASSERT(m_pDirectDrawSurface);
  304.     return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback);
  305. }
  306.  
  307.  
  308. STDMETHODIMP CAggDrawSurface::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags) {
  309.     ASSERT(m_pDirectDrawSurface);
  310.     return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags);
  311. }
  312.  
  313.  
  314. STDMETHODIMP CAggDrawSurface::GetAttachedSurface(LPDDSCAPS lpDDSCaps,LPDIRECTDRAWSURFACE *lplpDDAttachedSurface) {
  315.     ASSERT(m_pDirectDrawSurface);
  316.     return m_pDirectDrawSurface->GetAttachedSurface(lpDDSCaps,lplpDDAttachedSurface);
  317. }
  318.  
  319.  
  320. STDMETHODIMP CAggDrawSurface::GetBltStatus(DWORD dwFlags) {
  321.     ASSERT(m_pDirectDrawSurface);
  322.     return m_pDirectDrawSurface->GetBltStatus(dwFlags);
  323. }
  324.  
  325.  
  326. STDMETHODIMP CAggDrawSurface::GetCaps(LPDDSCAPS lpDDSCaps) {
  327.     ASSERT(m_pDirectDrawSurface);
  328.     return m_pDirectDrawSurface->GetCaps(lpDDSCaps);
  329. }
  330.  
  331.  
  332. STDMETHODIMP CAggDrawSurface::GetClipper(LPDIRECTDRAWCLIPPER *lplpDDClipper) {
  333.     ASSERT(m_pDirectDrawSurface);
  334.     return m_pDirectDrawSurface->GetClipper(lplpDDClipper);
  335. }
  336.  
  337.  
  338. STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey) {
  339.     ASSERT(m_pDirectDrawSurface);
  340.     return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey);
  341. }
  342.  
  343.  
  344. STDMETHODIMP CAggDrawSurface::GetDC(HDC *lphDC) {
  345.     ASSERT(m_pDirectDrawSurface);
  346.     return m_pDirectDrawSurface->GetDC(lphDC);
  347. }
  348.  
  349.  
  350. STDMETHODIMP CAggDrawSurface::GetFlipStatus(DWORD dwFlags) {
  351.     ASSERT(m_pDirectDrawSurface);
  352.     return m_pDirectDrawSurface->GetFlipStatus(dwFlags);
  353. }
  354.  
  355.  
  356. STDMETHODIMP CAggDrawSurface::GetOverlayPosition(LPLONG lpdwX,LPLONG lpdwY) {
  357.     ASSERT(m_pDirectDrawSurface);
  358.     return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY);
  359. }
  360.  
  361.  
  362. STDMETHODIMP CAggDrawSurface::GetPalette(LPDIRECTDRAWPALETTE *lplpDDPalette) {
  363.     ASSERT(m_pDirectDrawSurface);
  364.     return m_pDirectDrawSurface->GetPalette(lplpDDPalette);
  365. }
  366.  
  367.  
  368. STDMETHODIMP CAggDrawSurface::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) {
  369.     ASSERT(m_pDirectDrawSurface);
  370.     return m_pDirectDrawSurface->GetPixelFormat(lpDDPixelFormat);
  371. }
  372.  
  373.  
  374. // A bit of a warning here: Our media samples in DirectShow aggregate on
  375. // IDirectDraw and IDirectDrawSurface (ie are available through IMediaSample
  376. // by QueryInterface). Unfortunately the underlying DirectDraw code cannot
  377. // be aggregated so we have to use these classes. The snag is that when we
  378. // call a different surface and pass in this interface as perhaps the source
  379. // surface the call will fail because DirectDraw dereferences the pointer to
  380. // get at its private data structures. Therefore we supply this workaround to give
  381. // access to the real IDirectDraw surface. A filter can call GetSurfaceDesc
  382. // and we will fill in the lpSurface pointer with the real underlying surface
  383.  
  384. STDMETHODIMP CAggDrawSurface::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) {
  385.     ASSERT(m_pDirectDrawSurface);
  386.  
  387.     // First call down to the underlying DirectDraw
  388.  
  389.     HRESULT hr = m_pDirectDrawSurface->GetSurfaceDesc(lpDDSurfaceDesc);
  390.     if(FAILED(hr)) {
  391.         return hr;
  392.     }
  393.  
  394.     // Store the real DirectDrawSurface interface
  395.     lpDDSurfaceDesc->lpSurface = m_pDirectDrawSurface;
  396.     return hr;
  397. }
  398.  
  399.  
  400. STDMETHODIMP CAggDrawSurface::Initialize(LPDIRECTDRAW lpDD,LPDDSURFACEDESC lpDDSurfaceDesc) {
  401.     ASSERT(m_pDirectDrawSurface);
  402.     return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc);
  403. }
  404.  
  405.  
  406. STDMETHODIMP CAggDrawSurface::IsLost() {
  407.     ASSERT(m_pDirectDrawSurface);
  408.     return m_pDirectDrawSurface->IsLost();
  409. }
  410.  
  411.  
  412. STDMETHODIMP CAggDrawSurface::Lock(LPRECT lpDestRect,LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent) {
  413.     ASSERT(m_pDirectDrawSurface);
  414.     return m_pDirectDrawSurface->Lock(lpDestRect,lpDDSurfaceDesc,dwFlags,hEvent);
  415. }
  416.  
  417.  
  418. STDMETHODIMP CAggDrawSurface::ReleaseDC(HDC hDC) {
  419.     ASSERT(m_pDirectDrawSurface);
  420.     return m_pDirectDrawSurface->ReleaseDC(hDC);
  421. }
  422.  
  423.  
  424. STDMETHODIMP CAggDrawSurface::Restore() {
  425.     ASSERT(m_pDirectDrawSurface);
  426.     return m_pDirectDrawSurface->Restore();
  427. }
  428.  
  429.  
  430. STDMETHODIMP CAggDrawSurface::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) {
  431.     ASSERT(m_pDirectDrawSurface);
  432.     return m_pDirectDrawSurface->SetClipper(lpDDClipper);
  433. }
  434.  
  435.  
  436. STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey) {
  437.     ASSERT(m_pDirectDrawSurface);
  438.     return m_pDirectDrawSurface->SetColorKey(dwFlags,lpDDColorKey);
  439. }
  440.  
  441.  
  442. STDMETHODIMP CAggDrawSurface::SetOverlayPosition(LONG dwX,LONG dwY) {
  443.     ASSERT(m_pDirectDrawSurface);
  444.     return m_pDirectDrawSurface->SetOverlayPosition(dwX,dwY);
  445. }
  446.  
  447.  
  448. STDMETHODIMP CAggDrawSurface::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) {
  449.     ASSERT(m_pDirectDrawSurface);
  450.     return m_pDirectDrawSurface->SetPalette(lpDDPalette);
  451. }
  452.  
  453.  
  454. STDMETHODIMP CAggDrawSurface::Unlock(LPVOID lpSurfaceData) {
  455.     ASSERT(m_pDirectDrawSurface);
  456.     return m_pDirectDrawSurface->Unlock(lpSurfaceData);
  457. }
  458.  
  459.  
  460. STDMETHODIMP CAggDrawSurface::UpdateOverlay(LPRECT lpSrcRect,LPDIRECTDRAWSURFACE lpDDDestSurface,LPRECT lpDestRect,DWORD dwFlags,LPDDOVERLAYFX lpDDOverlayFX) {
  461.     ASSERT(m_pDirectDrawSurface);
  462.     return m_pDirectDrawSurface->UpdateOverlay(lpSrcRect,lpDDDestSurface,lpDestRect,dwFlags,lpDDOverlayFX);
  463. }
  464.  
  465.  
  466. STDMETHODIMP CAggDrawSurface::UpdateOverlayDisplay(DWORD dwFlags) {
  467.     ASSERT(m_pDirectDrawSurface);
  468.     return m_pDirectDrawSurface->UpdateOverlayDisplay(dwFlags);
  469. }
  470.  
  471.  
  472. STDMETHODIMP CAggDrawSurface::UpdateOverlayZOrder(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSReference) {
  473.     ASSERT(m_pDirectDrawSurface);
  474.     return m_pDirectDrawSurface->UpdateOverlayZOrder(dwFlags,lpDDSReference);
  475. }
  476.  
  477.  
  478. // DirectShow must work on multiple platforms.  In particular, it also runs on
  479. // Windows NT 3.51 which does not have DirectDraw capabilities. The filters
  480. // cannot therefore link statically to the DirectDraw library. To make their
  481. // lives that little bit easier we provide this class that manages loading
  482. // and unloading the library and creating the initial IDirectDraw interface
  483.  
  484. CLoadDirectDraw::CLoadDirectDraw() :
  485.     m_pDirectDraw(NULL),
  486.     m_hDirectDraw(NULL) {
  487. }
  488.  
  489.  
  490. // Destructor forces unload
  491.  
  492. CLoadDirectDraw::~CLoadDirectDraw() {
  493.     ReleaseDirectDraw();
  494.  
  495.     if(m_hDirectDraw) {
  496.         NOTE("Unloading library");
  497.         FreeLibrary(m_hDirectDraw);
  498.     }
  499. }
  500.  
  501.  
  502. // We can't be sure that DirectDraw is always available so we can't statically
  503. // link to the library. Therefore we load the library, get the function entry
  504. // point addresses and call them to create the driver objects. We return S_OK
  505. // if we manage to load DirectDraw correctly otherwise we return E_NOINTERFACE
  506. // We initialise a DirectDraw instance by explicitely loading the library and
  507. // calling GetProcAddress on the DirectDrawCreate entry point that it exports
  508.  
  509. // On a multi monitor system, we can get the DirectDraw object for any
  510. // monitor (device) with the optional szDevice parameter
  511.  
  512. HRESULT CLoadDirectDraw::LoadDirectDraw(LPSTR szDevice) {
  513.     PDRAWCREATE pDrawCreate;
  514.     PDRAWENUM pDrawEnum;
  515.     LPDIRECTDRAWENUMERATEEXA pDrawEnumEx;
  516.     HRESULT hr = NOERROR;
  517.  
  518.     NOTE("Entering DoLoadDirectDraw");
  519.  
  520.     // Is DirectDraw already loaded
  521.  
  522.     if(m_pDirectDraw) {
  523.         NOTE("Already loaded");
  524.         ASSERT(m_hDirectDraw);
  525.         return NOERROR;
  526.     }
  527.  
  528.     // Make sure the library is available
  529.  
  530.     if(!m_hDirectDraw) {
  531.         UINT ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  532.         m_hDirectDraw = LoadLibrary(TEXT("DDRAW.DLL"));
  533.         SetErrorMode(ErrorMode);
  534.  
  535.         if(m_hDirectDraw == NULL) {
  536.             DbgLog((LOG_ERROR,1,TEXT("Can't load DDRAW.DLL")));
  537.             NOTE("No library");
  538.             return E_NOINTERFACE;
  539.         }
  540.     }
  541.  
  542.     // Get the DLL address for the creator function
  543.  
  544.     pDrawCreate = (PDRAWCREATE)GetProcAddress(m_hDirectDraw,"DirectDrawCreate");
  545.     // force ANSI, we assume it
  546.     pDrawEnum = (PDRAWENUM)GetProcAddress(m_hDirectDraw,"DirectDrawEnumerateA");
  547.     pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(m_hDirectDraw,
  548.         "DirectDrawEnumerateExA");
  549.  
  550.     // We don't NEED DirectDrawEnumerateEx, that's just for multimon stuff
  551.     if(pDrawCreate == NULL || pDrawEnum == NULL) {
  552.         DbgLog((LOG_ERROR,1,TEXT("Can't get functions: Create=%x Enum=%x"),
  553.             pDrawCreate, pDrawEnum));
  554.         NOTE("No entry point");
  555.         ReleaseDirectDraw();
  556.         return E_NOINTERFACE;
  557.     }
  558.  
  559.     DbgLog((LOG_TRACE,3,TEXT("Creating DDraw for device %s"),
  560.         szDevice ? szDevice : "<NULL>"));
  561.  
  562.     // Create a DirectDraw display provider for this device, using the fancy
  563.     // multimon-aware version, if it exists
  564.     if(pDrawEnumEx)
  565.         m_pDirectDraw = DirectDrawCreateFromDeviceEx(szDevice, pDrawCreate,
  566.             pDrawEnumEx);
  567.     else
  568.         m_pDirectDraw = DirectDrawCreateFromDevice(szDevice, pDrawCreate,
  569.             pDrawEnum);
  570.  
  571.     if(m_pDirectDraw == NULL) {
  572.         DbgLog((LOG_ERROR,1,TEXT("Can't create DDraw")));
  573.         NOTE("No instance");
  574.         ReleaseDirectDraw();
  575.         return E_NOINTERFACE;
  576.     }
  577.     return NOERROR;
  578. }
  579.  
  580.  
  581. // Called to release any DirectDraw provider we previously loaded. We may be
  582. // called at any time especially when something goes horribly wrong and when
  583. // we need to clean up before returning so we can't guarantee that all state
  584. // variables are consistent so free only those really allocated allocated
  585. // This should only be called once all reference counts have been released
  586.  
  587. void CLoadDirectDraw::ReleaseDirectDraw() {
  588.     NOTE("Releasing DirectDraw driver");
  589.  
  590.     // Release any DirectDraw provider interface
  591.  
  592.     if(m_pDirectDraw) {
  593.         NOTE("Releasing instance");
  594.         m_pDirectDraw->Release();
  595.         m_pDirectDraw = NULL;
  596.     }
  597.  
  598. }
  599.  
  600.  
  601. // Return NOERROR (S_OK) if DirectDraw has been loaded by this object
  602.  
  603. HRESULT CLoadDirectDraw::IsDirectDrawLoaded() {
  604.     NOTE("Entering IsDirectDrawLoaded");
  605.  
  606.     if(m_pDirectDraw == NULL) {
  607.         NOTE("DirectDraw not loaded");
  608.         return S_FALSE;
  609.     }
  610.     return NOERROR;
  611. }
  612.  
  613.  
  614. // Return the IDirectDraw interface we look after
  615.  
  616. LPDIRECTDRAW CLoadDirectDraw::GetDirectDraw() {
  617.     NOTE("Entering GetDirectDraw");
  618.  
  619.     if(m_pDirectDraw == NULL) {
  620.         NOTE("No DirectDraw");
  621.         return NULL;
  622.     }
  623.  
  624.     NOTE("Returning DirectDraw");
  625.     m_pDirectDraw->AddRef();
  626.     return m_pDirectDraw;
  627. }
  628.  
  629.  
  630. // Are we running on Direct Draw version 1?  We need to find out as
  631. // we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To
  632. // find out, we simply see if it supports IDirectDraw2.  Only version 2 and
  633. // higher support this.
  634.  
  635. BOOL CLoadDirectDraw::IsDirectDrawVersion1() {
  636.  
  637.     if(m_pDirectDraw == NULL)
  638.         return FALSE;
  639.  
  640.     IDirectDraw2 *p = NULL;
  641.     HRESULT hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&p);
  642.     if(p)
  643.         p->Release();
  644.     if(hr == NOERROR) {
  645.         DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 2 or greater")));
  646.         return FALSE;
  647.     }
  648.     else {
  649.         DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 1")));
  650.         return TRUE;
  651.     }
  652. }
  653.  
  654.